package transaction;

import java.util.Enumeration;
import java.util.Set;
import java.util.concurrent.*;

import utils.Constants;

public class TxManager {

	private static ConcurrentHashMap<String, Integer> FileMap = 
		new ConcurrentHashMap<String, Integer>();
	static {
		FileMap.put(Constants.NODE_FILENAME, 0);
		FileMap.put(Constants.SET_FILENAME, 1);
		FileMap.put(Constants.SET_FILENAME_TEMP, 2);
		FileMap.put(Constants.SET_INODE_FILENAME, 3);
		FileMap.put(Constants.SET_INODE_FILENAME_TEMP, 4);
		FileMap.put(Constants.NODE_IDX_FILENAME, 5);
		FileMap.put(Constants.NODE_IDX_META_FILENAME, 6);
		FileMap.put(Constants.TAG_IDX_FILENAME, 7);
		FileMap.put(Constants.TAG_IDX_FILENAME_TEMP, 8);
		FileMap.put(Constants.TAG_IDX_INODE_FILENAME, 9);
		FileMap.put(Constants.TAG_IDX_INODE_FILENAME_TEMP, 10);
		FileMap.put(Constants.TAG_BPTree_FILENAME, 11);
		FileMap.put(Constants.ITEM_IDX_FILENAME, 12);
		FileMap.put(Constants.ITEM_IDX_INODE_FILENAME, 13);
		FileMap.put(Constants.ITEM_BPTree_FILENAME, 14);
		
	};
	
	
	/*public static final String TxBegin = "0 %1$d\n";
	public static final String TxCommit = "1 %1$d\n";
	public static final String AppendInt = "2 %1$d %2$d %3$d %4$d %5$d\n";
	public static final String AppendLong = "3 %1$d %2$d %3$d %4$d %5$d\n";
	public static final String AppendBytes = "4 %1$d %2$d %3$d %4$d %5$d %6$s\n";
	public static final String WriteInt = "5 %1$d %2$d %3$d %4$d %5$d %6$d\n";
	public static final String WriteLong = "6 %1$d %2$d %3$d %4$d %5$d %6$d\n";
	public static final String Other = "7 %1$s\n";*/
	
	public static final int TxBegin = 0;
	public static final int TxCommit = 1;
	public static final int AppendInt = 2;
	public static final int AppendLong = 3;
	public static final int AppendBytes = 4;
	public static final int WriteInt = 5;
	public static final int WriteLong = 6;
	public static final int LogInt = 7;
	public static final int LogStr = 8;
	
	
	public static final boolean EnableTransaction = true; 
	
	public static final boolean EnableRecovery = true;
	public static boolean WriteLog = true;
	
	
	private int txNum;
	private Object accessLock = new Object();
	
	private Logger logger;
	
	public TxManager() {
		txNum = 0;
		prepare();
		init();
	}
	
	private void prepare() {
		WriteLog = false;
		logger = new Logger();
		Recovery recover = new Recovery(this.newTransaction());
		recover.recover();
		logger.dispose();
	}
	
	private void init() {
		WriteLog = EnableRecovery;
		
		logger = new Logger();
		
		if (logger.NeedHeader) {
			Enumeration<String> str = FileMap.keys();
			Set<String> set = FileMap.keySet();
	
			logger.logInt(set.size());
			while (str.hasMoreElements()) {
				String key = str.nextElement();
				Integer value = FileMap.get(key);
				logger.logString(key);
				logger.logInt(value);
			}
		}
		
	}
	
	public Transaction newTransaction() {
		synchronized (accessLock) {
			return new Transaction(++txNum, logger, true);
		}
	}
	
	public Transaction newReadTransaction() {
		synchronized (accessLock) {
			return new Transaction(++txNum, logger, false);
		}
	}
	
	private static Integer pp = 7;
	public static int getFileId(String filename) {
		Integer value = FileMap.get(filename);
		if (value == null) {
			System.err.println(filename);
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
			/*synchronized (pp) {
				++pp;
				FileMap.put(filename, pp);
				value = pp;
			}*/
		}
		
		return value;
	}
	
	public void dispose() {
		logger.dispose();
	}
}
